﻿using System;
using System.Linq;
using CommonBehaviors.Actions;
using Styx.TreeSharp;
using Styx.CommonBot;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

using Action = Styx.TreeSharp.Action;

namespace PetBuddy.Helpers
{
    public class Healer
    {
        #region Variables

        private static LocalPlayer Me = PetBuddy.Me;

        const string    PET_HEAL_SPELL_NAME = "Revive Battle Pets";
        const int       PET_HEAL_SPELL_ID = 125439;
        const uint      PET_BANDAGE_ID = 86143;

        static readonly WoWSpell ReviveBattlePetsSpell = SpellManager.Spells.FirstOrDefault(s => s.Value.Id == PET_HEAL_SPELL_ID).Value;
        static readonly WoWItem PetBandage = Me.BagItems.FirstOrDefault(i => i != null && i.IsValid && i.Entry == PET_BANDAGE_ID);

        #endregion

        public static bool BattlePetsNeedHeal()
        {
            if (Fighter.IsInCombat) return false;

            var _needHealProc = PetBuddySettings.Instance.NeedHealProc;
            var _somePetNeedHeal = false;

            var msg = "Pets HP is  ";

            for (var i = 1; i <= 3; i++)
            {
                var info = PetJournal.GetPetLoadOutInfo(i);
                if (info.locked)
                {
                    msg += string.Format("[{0}]:-- ", i);
                    continue;
                }

                var stat = PetJournal.GetPetStats(info.petGUID);
                var healproc = (int)Math.Truncate((double)stat.health/(stat.maxHealth != 0 ? stat.maxHealth : 1)*100);
                msg += string.Format("[{0}]:{1}% ", i, healproc);

                if (healproc <= _needHealProc) _somePetNeedHeal = true;
            }

            msg += _somePetNeedHeal ? "Pets need heal" : "Pets looks alive for next fight";

            PetBuddy.dlog("[Healer] {0}", msg);
            return _somePetNeedHeal;
        }

        static bool CanCastHeal
        {
            get { return SpellManager.HasSpell(PET_HEAL_SPELL_ID) && SpellManager.CanCast(PET_HEAL_SPELL_ID); }
        }

        static bool CanUseBandages
        {
            get { return PetBandage != null && PetBandage.Cooldown <= 0 && PetBuddySettings.Instance.UseBandages; }
        }

        static bool StableIsActual 
        {
            get 
            {
                if (Stabler.NearestStableMaster.ID <= 0) return false;

                var distance = Me.Location.Distance(Stabler.NearestStableMaster.Location);

                PetBuddy.dlog("[Stabler] Distance to stable is {0}", distance);
                return !CanUseBandages && !CanCastHeal && ReviveBattlePetsSpell.CooldownTimeLeft.TotalSeconds > (distance / 30);
            }
        }

        public static Composite HealPetsBehavior()
        {
            return new PrioritySelector(

                new Decorator(ret => PetBuddySettings.Instance.UseStables && Stabler.HaveStableList && StableIsActual,
                              new Sequence(
                                  PetBuddy.aslog("[Healer] Go to Stable"),
                                  Stabler.UseNearestStable(),
                                  new Action(ret => PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE),
                                  new ActionAlwaysSucceed()
                                  )),

                new Decorator(ret => CanUseBandages,
                              new Sequence(
                                  PetBuddy.aslog("[Healer] Use Pet Bandages"),
                                  new Action(ret => Mover.navSelector = Mover.NavSelector.LANDING),
                                  Mover.MoveToTargetNavPoint(),
                                  new Action(ret =>
                                      {
                                          if (PetBandage == null)
                                              return RunStatus.Failure;
                                          PetBandage.Interact();
                                          PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE;
                                          return RunStatus.Success;
                                      })
                                  )),

                new Decorator(ret => ReviveBattlePetsSpell.Cooldown,
                              new Sequence(
                                  PetBuddy.aslog("[Healer] Wait for PetHeal colldown left"),
                                  new Action(ret => Mover.navSelector = Mover.NavSelector.WAIT),
                                  Mover.MoveToTargetNavPoint(),
                                  new PrioritySelector(

                                      new Decorator(ret => ReviveBattlePetsSpell.CooldownTimeLeft.TotalSeconds > 0,
                                                    new Wait(1, new ActionIdle())
                                          ),

                                      new Decorator(ret => ReviveBattlePetsSpell.CooldownTimeLeft.TotalSeconds <= 0,
                                                    new Action(ret =>
                                                        {
                                                            PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE;
                                                            return RunStatus.Success;
                                                        })
                                          )
                                      ),
                                  new ActionAlwaysFail()
                                  )),

                new Decorator(ret => CanCastHeal,
                              new Sequence(
                                  PetBuddy.aslog("[Healer] Use Pet Heal"),
                                  new Action(ret => SpellManager.Cast(PET_HEAL_SPELL_NAME, Me)),
                                  new Action(ret => PetBuddy.BotRunStatus.flag = PetBuddy.BotRunStatusEnum.IDLE),
                                  new ActionAlwaysSucceed()
                                  )),

                new ActionAlwaysFail()
                );
        }
    }
}
